use crate::Tensor;

pub fn broadcast_shapes(shapes: &[&[usize]]) -> Box<[usize]> {
    let shapes = shapes.as_ref();
    let shapes_count = shapes.len();
    let max_len = shapes.iter()
        .map(|shape| shape.as_ref().len())
        .max()
        .unwrap_or(0);

    if max_len == 0 {
        return vec![].into_boxed_slice();
    }

    let shapes = shapes.iter()
        .map(|shape| {
            let mut shape = shape
                .as_ref()
                .into_iter()
                .rev()
                .copied()
                .collect::<Vec<usize>>();
            shape.extend((0..(max_len - shape.len())).map(|_| 1));
            shape
        })
        .flatten()
        .collect::<Vec<usize>>();

    unimplemented!()

    // let shapes = shapes
    //     .reshape(&[shapes_count, max_len])
    //     .t();
    //
    // (0..max_len)
    //     .into_iter()
    //     .map(|i| {
    //         let dims = shapes.index(&[i]);
    //         let max_dim = dims
    //             .flat_iter()
    //             .max()
    //             .unwrap_or(1);
    //         shapes.index(&[i])
    //             .flat_iter()
    //             .all(|x| x == 1 || x == max_dim)
    //             .then(|| max_dim)
    //             .expect("shape mismatch: objects cannot be broadcast to a single shape.")
    //     })
    //     .rev()
    //     .collect::<Box<[usize]>>()
}

pub fn shape_to_strides(shape: &[usize]) -> Box<[usize]> {
    let initial: usize = shape.iter().product();
    shape.iter()
        .scan(initial, |acc, size| {
            *acc = *acc / *size;
            (*acc).into()
        })
        .collect()
}
